import { ObjectId } from "mongodb"
import { sendLogMessageTo } from "../listen"
import db from "../db"
import { FetchAPI, ChatMessage, BaseInfo, ChatRoom, LoginUser, ChatMessageType } from "../interfaces"
import { message_render } from '../utils/message_render'
import { ERRORS, getBaseInfo } from "../utils/common"
import { getRobotResponse } from "../utils/users"

const hasErrors = (chatroom: ChatRoom & BaseInfo, loginUser: LoginUser) => {
  if (!chatroom || chatroom.is_deleted) {
    return {
      error: ERRORS.CHATROOM_404
    }
  }
  /** 群主权限最高 */
  if (loginUser.username === chatroom.created_by) {
    return
  }
  /** 有无权限, 发言需要群主或者未被禁言的用户 */
  for (let i = 0; i < chatroom.users.length; i++) {
    const user = chatroom.users[i];
    if (user.username === loginUser.username) {
      if (user.is_admin || user.is_master) {
        return
      }
      if (chatroom.is_muted || user.is_muted) {
        return {
          error: ERRORS.MUTED_YOU
        }
      } else {
        return
      }
    }
  }
  return {
    error: ERRORS.PERMISSION_DENIED
  }
}

/** 发送消息 */
export const message_send: FetchAPI<ChatMessage, ChatMessage & BaseInfo> = async (
  _msg,
  { loginUser },
) => {
  const msg = message_render(_msg)
  const conn = await db.getCollection('chatroom')
  const conn_log = await db.getCollection('log')
  const chatroom = await conn.findOne({ _id: new ObjectId(msg.chatroom_id), "users.username": loginUser.username, })
  const errors = hasErrors(chatroom, loginUser)
  if (errors) {
    return errors
  }
  const baseInfo = getBaseInfo(loginUser)
  const info: ChatMessage & BaseInfo = {
    ...msg,
    ...baseInfo,
  }
  const to = chatroom.users.map(u => u.username)
  const logBaseInfo = getBaseInfo(loginUser)
  const { insertedId } = await conn_log.insertOne({ type: 'message_send', message: info, chatroom_id: chatroom._id, to, ...logBaseInfo })
  info._id = insertedId
  sendLogMessageTo(to, 'message_send', info, { _id: insertedId, ...logBaseInfo }, chatroom._id)

  // 机器人的异步回应
  getRobotResponse(_msg.body).then(res => {
    if (res && res.length > 0) {
      res.forEach(({ name, result }) => {
        message_send({ body: `@${loginUser.name} ` + result, type: ChatMessageType.TXT, chatroom_id: chatroom._id }, { loginUser: { username: name, name, token: name } })
      })
    }
  })

  return {
    success: true,
    data: info,
  }
}

/** 消息撤回 */
export const message_cancel: FetchAPI<{ _id: BaseInfo['_id'] }, ChatMessage & BaseInfo> = async (
  msg,
  { loginUser },
) => {
  const conn = await db.getCollection('chatroom')
  const conn_log = await db.getCollection('log')
  const log = await conn_log.findOne({ _id: new ObjectId(msg._id), type: 'message_send' })
  if (!log) {
    return {
      error: ERRORS.MESSAGE_404
    }
  }
  const chatroom = await conn.findOne({ _id: new ObjectId(log.chatroom_id) })
  const errors = hasErrors(chatroom, loginUser)
  if (errors) {
    return errors
  }

  const baseInfo = getBaseInfo(loginUser, log)
  const info = {
    ...(log.message as ChatMessage),
    canceled: true,
    ...baseInfo,
  }
  const logBaseInfo = getBaseInfo(loginUser)
  await conn_log.updateOne({ _id: log._id }, {
    $set: {
      type: 'message_cancel',
      message: info,
      ...logBaseInfo,
    }
  })
  const to = chatroom?.users.map(u => u.username) || []
  sendLogMessageTo(to, 'message_cancel', info, { _id: msg._id, ...logBaseInfo }, chatroom._id)
  return {
    success: true,
    data: info,
  }
}
